import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException; 
import javax.sound.sampled.Mixer;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.TargetDataLine;

public class AudioHandling {

	protected static boolean running;
	private static DatagramSocket socket = null;
	private static InetAddress[] membershipList = null;
	private static int packetCounter = 0;

	private static AudioFormat getFormat() {
		float sampleRate = 8000;
		int sampleSizeInBits = 8;
		int channels = 1;
		boolean signed = true;
		boolean bigEndian = true;
		return new AudioFormat(sampleRate, sampleSizeInBits, channels, signed,
				bigEndian);
	}

	private static void bootstrapSocket(AudioFormat format, int bufferSize,
			InetAddress[] membershipList) {
		try {
			// This is the socket for sending outgoing packets
			socket = new DatagramSocket();

			// This is the socket for incoming packets
			DatagramSocket incomingSocket = new DatagramSocket(55556);
			new PacketCaptureThread(incomingSocket, format, bufferSize,
					membershipList).start();

		} catch (SocketException e) {
			e.printStackTrace();
		}

	}

	private static void captureAudio(AudioFormat format, final int bufferSize) {
		try {
			DataLine.Info targetInfo = new DataLine.Info(TargetDataLine.class, format);
			final TargetDataLine targetLine = (TargetDataLine) AudioSystem.getLine(targetInfo);
			targetLine.open(format);
			targetLine.start();

			/*
			DataLine.Info sourceInfo = new
			DataLine.Info(SourceDataLine.class, format); final SourceDataLine
			sourceLine = (SourceDataLine) AudioSystem.getLine(sourceInfo);
			sourceLine.open(format); sourceLine.start();
			*/
			
			Runnable runner = new Runnable() {
				byte[] buffer = new byte[bufferSize];

				public void run() {
					running = true;
					while (running) {
						int count = targetLine.read(buffer, 0, buffer.length);
						if (count > 0) {
							for (int i = 0; i < membershipList.length; i++) {
								try {
									DatagramPacket outboundPacket = new DatagramPacket(
											buffer, buffer.length,
											membershipList[i], 55556);
									socket.send(outboundPacket);
									System.out.println("Sent " + packetCounter
											+ " Datagram packets.");
									packetCounter++;
								} catch (IOException e) {
									e.printStackTrace();
								}
							}
							// If you want to hear what you just sent out,
							// uncomment the line below.
							// sourceLine.write(buffer, 0, count);
						}
					}
				}
			};
			Thread captureThread = new Thread(runner);
			captureThread.start();
		} catch (LineUnavailableException e) {
			System.err.println("Line unavailable: " + e);
			System.exit(-2);
		}
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// This is just here for testing
		try {
			membershipList = new InetAddress[1];
			membershipList[0] = InetAddress.getLocalHost();
			//membershipList[0] = InetAddress.getByName("10.0.0.151");
			//membershipList[1] = InetAddress.getByName("10.0.0.200");
		} catch (UnknownHostException e) {
			e.printStackTrace();
		}

		AudioFormat format = getFormat();
		int bufferSize = (int) format.getSampleRate() * format.getFrameSize();

		bootstrapSocket(format, bufferSize, membershipList);

		captureAudio(format, bufferSize);

	}

}
